﻿using System;
using System.IO;
using System.ServiceModel.Web;
using NCMIS.AccessControl;
using NCMIS.ObjectModel.Rest;
using NCMIS.Produce;
using NCMIS.Provider;

namespace NCMIS.ServiceModel.Ra
{
    /// <summary>
    /// Provides the ACL Services for the REST/Atom binding. 
    /// </summary>
    public partial class Service : IService
    {
        /// <summary>
        /// Gets the ACL currently applied to the specified document or folder object.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="onlyBasicPermissions">If true only the basic permissions (cmis:read, cmis:write and cmis:all) will be applied.</param>
        /// <returns>List of access control entries of the ACL for the object.</returns>
        [WebGet(UriTemplate = "/{repositoryId}/object/{objectId}/acl")]
        public Acl GetAcl(string repositoryId, string objectId)
        {
            bool onlyBasicPermissions = RequestParameter.OnlyBasicPermissions;

            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;

            if (String.IsNullOrEmpty(repositoryId) || String.IsNullOrEmpty(objectId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and objectId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return null;
            }

            return AclProviderManager.Provider.GetAcl(repositoryId, objectId, onlyBasicPermissions);
        }

        /// <summary>
        /// Adds or removes the given ACEs to or from the ACL of document or folder object.
        /// </summary>
        /// <param name="repositoryId">The id of the repository.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="addACEs">The ACEs to add.</param>
        /// <param name="removeACEs">The ACEs to remove.</param>
        /// <param name="aclPropagation">Specifies how ACEs should be handled.</param>
        /// <returns>List of access control entries of the resulting ACL for the object.</returns>
        [WebInvoke(Method = "PUT", UriTemplate = "/{repositoryId}/object/{objectId}/acl")]
        public Acl ApplyAcl(string repositoryId, string objectId, Stream stream)
        {
            // TODO: Retrieve from stream: AccessControlList addACEs, AccessControlList removeACEs, AclPropagation? aclPropagation

            OutgoingWebResponseContext ctx = WebOperationContext.Current.OutgoingResponse;

            if (String.IsNullOrEmpty(repositoryId) || String.IsNullOrEmpty(objectId))
            {
                ctx.StatusCode = ServiceException.InvalidArgument;
                ctx.StatusDescription = String.Format("{0}: The parameters repositoryId and objectId must not be null or empty.",
                    ServiceException.InvalidArgument.ToString());
                return null;
            }

            return AclProviderManager.Provider.ApplyAcl(repositoryId, objectId, null, null, AclPropagation.ObjectOnly);
        }
    }
}
